package projet.volleystat;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;

import projet.volleystat.automate.MarkedPointVolleyAction;
import projet.volleystat.automate.ReplacementVolleyAction;
import projet.volleystat.automate.VolleyAction;
import projet.volleystat.automate.VolleyStateMachine;
import projet.volleystat.automate.VolleyStatistic;
import projet.volleystat.bdd.VolleyRepository;
import android.content.Context;
import android.database.Cursor;

/**
 * @author Lameira Nelaupe Ferrand Fiore
 * @version 1.0 DBInfo est une classe qui permet de charger les joueurs dans la
 *          RAM afin d'etre utilise en plein match. Elle s'assure de ne pas
 *          faire de copie d'une meme ligne dans les tables de la base de
 *          donnees. Elle fonction ne grace aux fonctions chargees, qu'elle
 *          implante.
 */
public final class DBInfo {
	protected TreeMap<Integer, Team> loadedTeam;
	protected TreeMap<Integer, Player> loadedPlayer;
	protected VolleyRepository volleyDataBase;

	/**
	 * @param context
	 *            Creation de la base de donnees et initialisation des
	 *            arguments.
	 */
	public DBInfo(Context context) {
		loadedTeam = new TreeMap<Integer, Team>();
		loadedPlayer = new TreeMap<Integer, Player>();
		volleyDataBase = new VolleyRepository(context);
	}

	/**
	 * Teste des fonctions de la base de donnees.
	 */
	public void generateTry() {

		// On cree des joueurs
		Player lucas = new Player("Nelaupe", "Lucas", "Francais");
		Player yannick = new Player("Lameira", "Yannick", "Russe");
		Player cyrille = new Player("Fiore", "Cyrille", "Semi Asiatique");
		Player anthony = new Player("Ferrand", "Anthony", "?");

		// On ouvre la base de donnees
		volleyDataBase.open();
		volleyDataBase.reset();
		try {
			volleyDataBase.commit(lucas);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		try {
			volleyDataBase.commit(yannick);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		try {
			volleyDataBase.commit(cyrille);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		try {
			volleyDataBase.commit(anthony);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}

		// On Ajoute les Joueurs
		// On creer un joueur quelconque
		Player s;
		try {
			s = volleyDataBase.getPlayerById(lucas.getId());
		} catch (DatabaseException e) {
			e.printStackTrace();
		}

		// On change le nom
		cyrille.setName("Lameira");
		try {
			volleyDataBase.commit(cyrille);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}

		try {
			s = volleyDataBase.getPlayerById(cyrille.getId());
			System.out.println("Son nom est : " + s.getName());
		} catch (DatabaseException e) {
			e.printStackTrace();
		}

		// On declare une liste de Joueurs
		ArrayList<Player> listPlayer = new ArrayList<Player>();
		try {
			listPlayer = volleyDataBase.getAllPlayer();
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		System.out.println("-----Liste de tout les joueurs---");
		for (Player str : listPlayer) {
			System.out.println(str.getName());
		}
		System.out.println("------------------------------");

		Team team = new Team("team", "United States Of China");
		try {
			volleyDataBase.commit(team);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}

		Team eq;
		try {
			eq = volleyDataBase.getTeamById(team.getId());
			System.out.println(eq.getName());
		} catch (DatabaseException e) {
			e.printStackTrace();
		}

		System.out.println("Ceci va bugger : ");
		team.setName("World Team");
		try {
			volleyDataBase.commit(team);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		System.out.println("Suite");
		try {
			eq = volleyDataBase.getTeamById(team.getId());
			System.out.println(eq.getName());
		} catch (DatabaseException e6) {
			e6.printStackTrace();
		}

		try {
			volleyDataBase.associate(lucas, team);
		} catch (DatabaseException e1) {
			e1.printStackTrace();
		}

		try {
			volleyDataBase.associate(cyrille, team);
		} catch (DatabaseException e5) {
			e5.printStackTrace();
		}

		try {
			volleyDataBase.associate(cyrille, team);
		} catch (DatabaseException e5) {
			e5.printStackTrace();
		}

		System.out.println("Liste des Joueurs dans l'equipe");
		ArrayList<Player> listPlayerTeam = new ArrayList<Player>();
		try {
			listPlayerTeam = volleyDataBase.getAllPlayerInTeam(team);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		for (Player str : listPlayerTeam) {
			System.out.println(str.getName());
		}
		System.out.println("--------------");

		ArrayList<Team> listTeam = new ArrayList<Team>();
		try {
			listTeam = volleyDataBase.getAllTeam();
		} catch (DatabaseException e4) {
			e4.printStackTrace();
		}
		for (Team str : listTeam) {
			System.out.println(str.getName());
		}
		System.out.println("--------------");

		try {
			volleyDataBase.delete(team);
		} catch (DatabaseException e3) {
			e3.printStackTrace();
		}

		try {
			volleyDataBase.delete(lucas);
		} catch (DatabaseException e2) {
			e2.printStackTrace();
		}
		try {
			volleyDataBase.delete(cyrille);
		} catch (DatabaseException e1) {
			e1.printStackTrace();
		}
		try {
			volleyDataBase.delete(yannick);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		try {
			volleyDataBase.delete(anthony);
		} catch (DatabaseException e) {
			e.printStackTrace();
		}
		volleyDataBase.close();
	}

	/**
	 * @return TreeMap<Integer, Team> Recupere l'arbre rouge noir associant les
	 *         equipes.
	 * @see getAllTeams()
	 */
	public TreeMap<Integer, Team> getLoadedTeam() {
		return loadedTeam;
	}

	/**
	 * @param loadedTeam
	 *            Defini l'arbre rouge noir a equipesChargees.
	 */
	public void setLoadedTeam(TreeMap<Integer, Team> loadedTeam) {
		this.loadedTeam = loadedTeam;
	}

	/**
	 * @param key
	 * @return Team
	 * @throws DatabaseException
	 *             Recupere une equipe grace a son id clef, si elle n'est pas
	 *             chargee, une DatabaseException est levee.
	 */
	public Team getTeam(Integer key) throws DatabaseException {
		if (loadedTeam.containsKey(key)) {
			return loadedTeam.get(key);
		} else {
			// Catchable pour proposer l'entraineur d'integrer l'equipe
			// manquante.
			throw new DatabaseException(
					"L'equipe n'est pas chargee ou n'existe pas.");
		}
	}

	/**
	 * @param key
	 * @return
	 * @throws DatabaseException
	 *             Recupere un joueur grace a son id clef, si il n'est pas
	 *             charge, une DatabaseException est levee.
	 */
	public Player getPlayer(Integer key) throws DatabaseException {
		if (loadedPlayer.containsKey(key)) {
			return loadedPlayer.get(key);
		} else {
			// Catchable pour proposer a l'entraineur d'integrer l'equipe
			// manquante.
			throw new DatabaseException(
					"Le joueur n'est pas charge ou n'existe pas.");
		}
	}

	/**
	 * @return ArrayList<Team> Renvoie une liste de toutes les equipes chargees.
	 */
	public ArrayList<Team> getAllTeams() {
		return (ArrayList<Team>) (loadedTeam.values());
	}

	/**
	 * @return ArrayList<Player> Renvoie une liste de tous les joueurs charges.
	 */
	public ArrayList<Player> getAllPlayers() {
		return (ArrayList<Player>) (loadedPlayer.values());
	}

	/**
	 * @throws DatabaseException
	 *             Charge en memoire toutes les equipes et joueurs de la base de
	 *             donnees.
	 */
	public void loadAll() throws DatabaseException {
		volleyDataBase.open();
		loadAllTeam();
		loadAllPlayer();
		volleyDataBase.close();
	}

	/**
	 * @throws DatabaseException
	 *             Charge en memoire toutes les equipes de la base de donnees
	 *             (fonction interne).
	 */
	protected void loadAllTeam() throws DatabaseException {
		for (Team team : volleyDataBase.getAllTeam()) {
			loadedTeam.put(team.getId(), team);
			for (Player player : team.getPlayerlist()) {
				player.addTeam(team);
				if (!loadedPlayer.containsKey(player.getId())) {
					loadedPlayer.put(player.getId(), player);
				}
			}
		}
	}

	/**
	 * @throws DatabaseException
	 *             Charge en memoire tous les joueurs de la base de donnees
	 *             (fonction interne).
	 */
	protected void loadAllPlayer() throws DatabaseException {
		for (Player player : volleyDataBase.getAllPlayer()) {
			if (!loadedPlayer.containsKey(player.getId())) {
				loadedPlayer.put(player.getId(), player);
			}
		}
	}

	/*
	 * public void chargerEquipes(ArrayList<String> listeNomsEquipes) throws
	 * BaseDeDonneeException{ volleyDataBase.open(); for(Equipe equipe :
	 * volleyDataBase.GetAllEquipe()){
	 * if(listeNomsEquipes.contains(equipe.getNom())){
	 * equipesChargees.put(equipe.getId(), equipe); ArrayList<Integer>
	 * listeJoueursDansEquipe = equipe.getAllId(); for(Map.Entry<Integer,
	 * Joueur> entry : joueursCharges.entrySet()) {
	 * if(listeJoueursDansEquipe.contains(entry.getKey())){
	 * entry.getValue().ajouterEquipe(equipe); } } } } }
	 * 
	 * public void chargerJoueurs(ArrayList<String> listeNomsJoueurs) throws
	 * BaseDeDonneeException{ volleyDataBase.open(); for(Joueur joueur :
	 * volleyDataBase.GetAllJoueur()){
	 * if(listeNomsJoueurs.contains(joueur.getNom())){
	 * joueursCharges.put(joueur.getId(), joueur); for(Map.Entry<Integer,
	 * Equipe> entry : equipesChargees.entrySet()) {
	 * if(entry.getValue().getAllId().contains(joueur.getId())){
	 * joueur.ajouterEquipe(entry.getValue()); } } } } volleyDataBase.close(); }
	 */

	/**
	 * @param player
	 * @throws DatabaseException
	 *             Sauvegarde joueur dans la base de donnees.
	 */
	public void saveNewPlayer(Player player) throws DatabaseException {
		volleyDataBase.open();
		volleyDataBase.commit(player);
		volleyDataBase.close();
	}

	/**
	 * @param team
	 * @throws DatabaseException
	 *             Sauve equipe dans la base de donnees.
	 */
	public void saveNewTeam(Team team) throws DatabaseException {
		volleyDataBase.open();
		volleyDataBase.commit(team);
		volleyDataBase.close();
	}

	/**
	 * @param listNameTeam
	 * @throws DatabaseException
	 *             Supprime de la memoire les equipes ayant un nom compris dans
	 *             listeNomsEquipes.
	 */
	public void removeTeams(ArrayList<String> listNameTeam)
			throws DatabaseException {
		volleyDataBase.open();
		for (String nameTeam : listNameTeam) {
			for (Map.Entry<Integer, Team> entry : loadedTeam.entrySet()) {
				if (entry.getValue().getName().equals(nameTeam)) {
					for (Player player : entry.getValue().getPlayerlist()) {
						player.removeTeam(entry.getValue());
					}
					loadedTeam.remove(entry.getKey());
				}
			}
		}
		volleyDataBase.close();
	}

	/**
	 * @param listNamePlayer
	 * @throws DatabaseException
	 *             Supprime de la memoire les joueurs ayant un nom compris dans
	 *             listeNomsJoueurs.
	 */
	public void removePlayers(ArrayList<String> listNamePlayer)
			throws DatabaseException {
		volleyDataBase.open();
		for (String nemePlayer : listNamePlayer) {
			for (Map.Entry<Integer, Player> entry : loadedPlayer.entrySet()) {
				if (entry.getValue().getName().equals(nemePlayer)) {
					loadedPlayer.remove(entry.getKey());
				}
			}

		}
		volleyDataBase.close();
	}

	/**
	 * @throws DatabaseException
	 *             Enregistre toutes les equipes chargees dans la base de
	 *             donnees.
	 */
	public void submit() throws DatabaseException {
		volleyDataBase.open();
		for (Map.Entry<Integer, Team> entry : loadedTeam.entrySet()) {
			volleyDataBase.commit(entry.getValue());
		}
		volleyDataBase.close();
	}

	/**
	 * @return TreeMap <Integer, Player> Recupere les joueurs charges en
	 *         memoire.
	 */
	public TreeMap<Integer, Player> getjoueursCharges() {
		return loadedPlayer;
	}

	/**
	 * @param loadedPlayer
	 *            Defini les joueurs charges a joueursCharges.
	 */
	public void setLoadedPlayer(TreeMap<Integer, Player> loadedPlayer) {
		this.loadedPlayer = loadedPlayer;
	}

	/**
	 * Ouvre la base de donnees, ne pas oublier de la fermer ensuite.
	 * 
	 * @see closeDb()
	 */
	public void openDb() {
		volleyDataBase.open();
	}

	/**
	 * Ferme la base de donnees.
	 * 
	 * @see openDb()
	 */
	public void closeDb() {
		volleyDataBase.close();
	}

	/**
	 * @return VolleyRepository Recupere la base de donnees.
	 */
	public VolleyRepository getDb() {
		return volleyDataBase;
	}

	/**
	 * @param order
	 * @return Cursor
	 * @throws DatabaseException
	 *             Recupere un cursor de tous les joueurs dans la base de
	 *             donnees.
	 */
	public Cursor getAllJoueursCursor(String order) throws DatabaseException {
		return volleyDataBase.getAllCursorPlayer(order);
	}

	/**
	 * @param order
	 * @return Cursor
	 * @throws DatabaseException
	 *             Recupere un cursor de toutes les equipes dans la base de
	 *             donnees.
	 */
	public Cursor getAllEquipeCursor(String order) throws DatabaseException {
		return volleyDataBase.getAllCursorTeam(order);
	}

	/*
	 * /**
	 * 
	 * @param machine
	 * 
	 * @throws DatabaseException Enregistre toute les statistiques du match
	 * d�crit dans machine.
	 */
	public int registerMatch(VolleyStateMachine machine)
			throws DatabaseException {
		volleyDataBase.open();
		int idMatch = volleyDataBase.getIdGameHigher() + 1;
		int idTargetPlayer = -1;
		for (VolleyAction action : machine.getActionHistoric()) {
			switch (action.getId()) {
			case 30:
				idTargetPlayer = ((MarkedPointVolleyAction) action)
						.getTargetPlayer().getId();
				break;
			case 31:
				idTargetPlayer = ((ReplacementVolleyAction) action)
						.getReplacingPlayer().getId();
				break;
			}
			volleyDataBase.commit(action.getId(), action.getTeam().getId(),
					action.getPlayer().getId(), idMatch, idTargetPlayer,
					action.getMark());
		}
		volleyDataBase.close();
		return idMatch;
	}

	/**
	 * @param idPlayer
	 * @return ArrayList<TreeMap<String, Integer> >
	 * @throws DatabaseException
	 *             Retourne la liste des actions d'un joueur.
	 */
	public ArrayList<TreeMap<String, Integer>> playerStat(int idPlayer)
			throws DatabaseException {
		volleyDataBase.open();
		ArrayList<TreeMap<String, Integer>> res = volleyDataBase
				.getStatPlayer(idPlayer);
		volleyDataBase.close();
		return res;
	}

	/**
	 * @param idPlayer
	 * @param idMatch
	 * @return ArrayList<TreeMap<String, Integer> >
	 * @throws DatabaseException
	 *             Retourne la liste des actions d'un joueur pendant un match.
	 */
	public ArrayList<TreeMap<String, Integer>> playerStatDuringMatch(
			int idPlayer, int idMatch) throws DatabaseException {
		volleyDataBase.open();
		ArrayList<TreeMap<String, Integer>> res = volleyDataBase.getStatPlayer(
				idPlayer, idMatch);
		volleyDataBase.close();
		return res;
	}

	/**
	 * @param idPlayer
	 * @param idMatch
	 * @return ArrayList<TreeMap<String, Integer> >
	 * @throws DatabaseException
	 */
	public ArrayList<TreeMap<String, Integer>> matchStat(int idMatch)
			throws DatabaseException {
		volleyDataBase.open();
		ArrayList<TreeMap<String, Integer>> res = volleyDataBase
				.getStatMatch(idMatch);
		volleyDataBase.close();
		return res;
	}

	/**
	 * @param fileName
	 * @param infos
	 * @param players
	 * @throws IOException
	 *             Ecrit au format HTML les infos de la liste Players dans le
	 *             fichier fileName.
	 */
	public void exportToHTML(String fileName, ArrayList<String> infos,
			ArrayList<Player> players) throws IOException {
		VolleyStatistic statistic = new VolleyStatistic(this);
		FileWriter fileWriter = new FileWriter(fileName);
		String toWrite = "<!DOCTYPE html><html xmlns='http://www.w3.org/1999/xhtml'><head><meta charset='utf-8' /><title>Statistiques de volley-ball</title><style>.title {position: relative;text-align: center;font-size: xx-large;}</style></head><body><div class='title'>Statistiques de volley-ball</div><table border='1'><tr><th>Joueur</th>";
		if (infos.isEmpty()) {
			infos.add("service");
			infos.add("faute");
			infos.add("passe");
			infos.add("point");
			infos.add("reception");
			infos.add("remplacement");
			infos.add("scorePoint");
			infos.add("scoreReception");
			infos.add("scorePass");
		}
		for (String str : infos) {
			if (str == "service") {
				toWrite = toWrite.concat("<th>Nombre de services</th>");
			}
			if (str == "faute") {
				toWrite = toWrite.concat("<th>Nombre de fautes</th>");
			}
			if (str == "passe") {
				toWrite = toWrite.concat("<th>Nombre de passes</th>");
			}
			if (str == "point") {
				toWrite = toWrite.concat("<th>Nombre de points marqués</th>");
			}
			if (str == "reception") {
				toWrite = toWrite.concat("<th>Nombre de réceptions</th>");
			}
			if (str == "remplacement") {
				toWrite = toWrite.concat("<th>Nombre de remplacements</th>");
			}
			if (str == "scorePoint") {
				toWrite = toWrite
						.concat("<th>Note moyenne sur les points marqués</th>");
			}
			if (str == "scoreReception") {
				toWrite = toWrite
						.concat("<th>Note moyenne sur les réceptions</th>");
			}
			if (str == "scorePass") {
				toWrite = toWrite
						.concat("<th>Note moyenne sur les passes</th>");
			}
		}
		toWrite = toWrite.concat("</tr>");
		for (Player player : players) {
			toWrite = toWrite.concat("<tr>");
			TreeMap<String, String> res = statistic.formatResult(statistic
					.analysisPlayer(player.getId()));
			toWrite = toWrite.concat("<td>" + player.getName() + "</td>");
			for (String str : infos) {
				if (res.containsKey(str)) {
					toWrite = toWrite.concat("<td>" + res.get(str) + "</td>");
				}
			}
			toWrite = toWrite.concat("</tr>");
		}
		toWrite = toWrite.concat("</table></body></html>");
		fileWriter.write(toWrite);
		fileWriter.close();
	}

	/**
	 * @param fileName
	 * @param infos
	 * @param players
	 * @param idMatch
	 * @throws IOException
	 *             Ecrit au format HTML les infos de la liste Players pendant le
	 *             match dans le fichier fileName.
	 */
	public void exportToHTML(String fileName, ArrayList<String> infos,
			ArrayList<Player> players, int idMatch) throws IOException {
		VolleyStatistic statistic = new VolleyStatistic(this);
		FileWriter fileWriter = new FileWriter(fileName);
		String toWrite = "<!DOCTYPE html><html xmlns='http://www.w3.org/1999/xhtml'><head><meta charset='utf-8' /><title>Statistiques de volley-ball</title><style>.title {position: relative;text-align: center;font-size: xx-large;}</style></head><body><div class='title'>Statistiques de volley-ball</div><table border='1'><tr><th>Joueur</th>";
		if (infos.isEmpty()) {
			infos.add("service");
			infos.add("faute");
			infos.add("passe");
			infos.add("point");
			infos.add("reception");
			infos.add("remplacement");
			infos.add("scorePoint");
			infos.add("scoreReception");
			infos.add("scorePass");
			infos.add("ratioServiceDurantMatch");
			infos.add("ratioFauteDurantMatch");
			infos.add("ratioPasseDurantMatch");
			infos.add("ratioPointDurantMatch");
			infos.add("ratioReceptionDurantMatch");
			infos.add("ratioRemplacementDurantMatch");
		}
		for (String str : infos) {
			if (str == "service") {
				toWrite = toWrite.concat("<th>Nombre de services</th>");
			}
			if (str == "faute") {
				toWrite = toWrite.concat("<th>Nombre de fautes</th>");
			}
			if (str == "passe") {
				toWrite = toWrite.concat("<th>Nombre de passes</th>");
			}
			if (str == "point") {
				toWrite = toWrite.concat("<th>Nombre de points marqués</th>");
			}
			if (str == "reception") {
				toWrite = toWrite.concat("<th>Nombre de réceptions</th>");
			}
			if (str == "remplacement") {
				toWrite = toWrite.concat("<th>Nombre de remplacements</th>");
			}
			if (str == "scorePoint") {
				toWrite = toWrite
						.concat("<th>Note moyenne sur les points marqués</th>");
			}
			if (str == "scoreReception") {
				toWrite = toWrite
						.concat("<th>Note moyenne sur les réceptions</th>");
			}
			if (str == "scorePass") {
				toWrite = toWrite
						.concat("<th>Note moyenne sur les passes</th>");
			}
			if (str == "ratioServiceDurantMatch") {
				toWrite = toWrite
						.concat("<th>Ratio de service sur le match</th>");
			}
			if (str == "ratioFauteDurantMatch") {
				toWrite = toWrite
						.concat("<th>Ratio de faute sur le match</th>");
			}
			if (str == "ratioPasseDurantMatch") {
				toWrite = toWrite
						.concat("<th>Ratio de passe sur le match</th>");
			}
			if (str == "ratioPointDurantMatch") {
				toWrite = toWrite
						.concat("<th>Ratio de point marqué sur le match</th>");
			}
			if (str == "ratioReceptionDurantMatch") {
				toWrite = toWrite
						.concat("<th>Ratio de réception sur le match</th>");
			}
			if (str == "ratioRemplacementDurantMatch") {
				toWrite = toWrite
						.concat("<th>Ratio de remplacement sur le match</th>");
			}
		}
		toWrite = toWrite.concat("</tr>");
		for (Player player : players) {
			toWrite = toWrite.concat("<tr>");
			TreeMap<String, String> res = statistic.formatResult(statistic
					.analysisPlayerDuringMatch(player.getId(), idMatch));
			toWrite = toWrite.concat("<td>" + player.getName() + " "
					+ player.getFirstname() + "</td>");
			for (String str : infos) {
				if (res.containsKey(str)) {
					toWrite = toWrite.concat("<td>" + res.get(str) + "</td>");
				}
			}
			toWrite = toWrite.concat("</tr>");
		}
		toWrite = toWrite.concat("</table></body></html>");
		fileWriter.write(toWrite);
		fileWriter.close();
	}
}
